(* ================================================================== *)
(** Module I/O de gestion d'array partiels à 2 dimensions de booléens.
    (exemple, les memoires incompletes ram, rom, etc ... *)
(* ================================================================== *)

open BitReader
open BplibTypes
open BoolMatrix

(* ===================================================================== *)
(** Etant donné un bool option array, il faut le découper en mots correspondant
    aux valeurs des mots d'une ram. Si le code est trop court, le reste 
    est mis a false. 
    @param taille le nombre de cases mémoire souhaitée
    @param lg_mot la longueur des mots mémoires en nombre de bit
    @param code un tableau à une dimension 
    @return m une matrice mémoire fraiche contenant les bits de code découpés
    selon le format demandé *)
(* ===================================================================== *)
let of_bool_option_array taille lg_mot code = 
  let len_donnee = Array.length code in
  let ff i = 
    if i < len_donnee
    then code.(i)
    else None
  in init_matrix_linear taille lg_mot ff

(* ===================================================================== *)
(** Lire une matrice bool incomplete dans un <b><i>fichier ascii</i></b>
    @param taille le nombre de cases mémoire souhaitée
    @param lg_mot la longueur des mots mémoires en nombre de bit
    @param filename le nom du fichier ascii contenant les bits ('0' et '1' et '*')
    @return m une matrice mémoire fraiche contenant les bits du fichier découpés
    selon le format demandé *)
(* ===================================================================== *)
let of_asci_file taille lg_mot filename = 
  let code = PartialBoolArray.of_asci_file filename in
  of_bool_option_array taille lg_mot code


(* ===================================================================== *)
(** Ecrire une matrice booléenne linéairement dans un <b><i>channel ascii</b></i> 
    @param ram une matrice mémoire
    @param oc le channel *)
(* ===================================================================== *)
let to_asci_channel ram oc = 
  let taille = Array.length ram and lg_mot = Array.length ram.(0) in
  for i = 0 to pred taille do
    for j = 0 to pred lg_mot do
      Printf.fprintf oc "%c" (char_of_bool_option ram.(i).(j))
    done;
    Printf.fprintf oc "\n"
  done


(* ===================================================================== *)
(** Ecrire une matrice booléenne linéairement dans un <b><i>fichier asci</b></i> 
    @param ram une matrice mémoire
    @param filename le nom du fichier à ouvrir en écriture *)
(* ===================================================================== *)
let to_asci_file ram filename = 
  let oc = open_out filename in
  to_asci_channel ram oc;
  close_out oc


(* ===================================================================== *)
(** test de conflit entre un tableau 2 dim partiel et un vrai tableau 2 dim.
    Si les tableaux n'ont pas la meme taille, on test les bits communs.
    @param partial_bits un tableau 2D partiel de bits 
    @param bits un tableau 2D de bit
    @return true si conflit, false sinon *)
(* ===================================================================== *)
let test_conflit partial_bits bits =
  let rec aux i = 
    if i < 0 then false
    else 
      if PartialBoolArray.test_conflit partial_bits.(i) bits.(i)
      then true
      else aux (pred i)
  in
  aux (pred (min (Array.length partial_bits) (Array.length bits)))


(* ===================================================================== *)
